package com.cardone.platform.authority.dao;

import java.util.List;
import java.util.Map;
import java.util.UUID;

import lombok.Getter;
import lombok.Setter;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import com.cardone.common.dto.PaginationDto;
import com.cardone.common.util.EntityUtils;
import com.cardone.context.Attributes;
import com.cardone.context.ContextHolder;
import com.cardone.persistent.builder.Model;
import com.cardone.persistent.builder.ModelArgs;
import com.cardone.persistent.builder.ModelUtils;
import com.cardone.persistent.support.JdbcTemplateSupport;
import com.cardone.persistent.support.PaginationArgs;
import com.cardone.platform.authority.dto.RoleUserDto;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * 角色与用户
 *
 * @author yaohaitao
 *
 */
@Getter
@Setter
public class RoleUserJdbcDao implements RoleUserDao {
	@Override
	public int deleteByIds(final RoleUserDto deleteRoleUser) {
		final Model model = ModelUtils.newModel();

		if (MapUtils.isNotEmpty(deleteRoleUser.getAttrs())) {
			model.putAll(deleteRoleUser.getAttrs());
		}

		model.put(Attributes.ids.name(), deleteRoleUser.getIds());

		model.putTrue(Model.Keys.whereAndBetween.stringValue(), Attributes.sysdate.name());

		return ContextHolder.getBean(JdbcTemplateSupport.class).update(SqlIds.deleteByIds.id(), model);
	}

	@Override
	public int deleteByRoleIds(final String roleIds) {
		final Map<String, Object> model = Maps.newHashMap();

		model.put("roleIds", roleIds);

		return ContextHolder.getBean(JdbcTemplateSupport.class).update(SqlIds.deleteByRoleIds.id(), model);
	}

	@Override
	public <P> P findByCodeOrId(final Class<P> mappedClass, final RoleUserDto findRoleUser) {
		final String[] whereAndEqProperties = EntityUtils.getWhereProperties(findRoleUser, Attributes.code.name());

		final Model model = ModelUtils.newModel(new ModelArgs(findRoleUser, whereAndEqProperties));

		if (MapUtils.isNotEmpty(findRoleUser.getAttrs())) {
			model.putAll(findRoleUser.getAttrs());
		}

		model.putTrue(Model.Keys.whereAndBetween.stringValue(), Attributes.sysdate.name());

		return ContextHolder.getBean(JdbcTemplateSupport.class).find(mappedClass, SqlIds.findByCode.id(), model);
	}

	@Override
	public <P> P findById(final Class<P> mappedClass, final RoleUserDto findRoleUser) {
		final String[] whereAndEqProperties = EntityUtils.getWhereProperties(findRoleUser);

		final Model model = ModelUtils.newModel(new ModelArgs(findRoleUser, whereAndEqProperties).setIsSimple(true));

		if (MapUtils.isNotEmpty(findRoleUser.getAttrs())) {
			model.putAll(findRoleUser.getAttrs());
		}

		return ContextHolder.getBean(JdbcTemplateSupport.class).find(mappedClass, SqlIds.findById.id(), model);
	}

	@Override
	public <P> List<P> findList(final Class<P> mappedClass) {
		return ContextHolder.getBean(JdbcTemplateSupport.class).findList(mappedClass, SqlIds.find.id(), null);
	}

	@Override
	public <P> List<P> findListByLikeCode(final Class<P> mappedClass, final RoleUserDto findListRoleUser) {
		final Model model = ModelUtils.newModel(new ModelArgs(findListRoleUser).setIsSimple(true));

		if (MapUtils.isNotEmpty(findListRoleUser.getAttrs())) {
			model.putAll(findListRoleUser.getAttrs());
		}

		return ContextHolder.getBean(JdbcTemplateSupport.class).findList(mappedClass, SqlIds.findByLikeCode.id(), model);
	}

	@Override
	public int insertByCode(final RoleUserDto insertRoleUser) {
		if (StringUtils.isBlank(insertRoleUser.getId())) {
			insertRoleUser.setId(UUID.randomUUID().toString());
		}

		final Model model = ModelUtils.newModel(new ModelArgs(Model.Keys.insert.stringValue(), insertRoleUser));

		if (MapUtils.isNotEmpty(insertRoleUser.getAttrs())) {
			model.putAll(insertRoleUser.getAttrs());
		}

		model.putTrue(Model.Keys.whereAndBetween.stringValue(), Attributes.sysdate.name());

		return ContextHolder.getBean(JdbcTemplateSupport.class).update(SqlIds.insertByCode.id(), model);
	}

	@Override
	public int insertByRoleCode(final List<RoleUserDto> insertRoleUserList) {
		if (CollectionUtils.isEmpty(insertRoleUserList)) {
			return 0;
		}

		final List<Map<String, Object>> modelList = Lists.newArrayList();

		for (final RoleUserDto insertRoleUser : insertRoleUserList) {
			final Map<String, Object> model = Maps.newHashMap();

			model.put(Attributes.roleCode.name(), insertRoleUser.getRoleCode());
			model.put(Attributes.userId.name(), insertRoleUser.getUserId());

			modelList.add(model);
		}

		return ContextHolder.getBean(JdbcTemplateSupport.class).update(SqlIds.insertByRoleCode.id(), modelList);
	}

	@Override
	public <P> PaginationDto<P> paginationByLikeCode(final Class<P> mappedClass, final RoleUserDto paginationRoleUser) {
		final Model model = ModelUtils.newModel(new ModelArgs(paginationRoleUser).setIsSimple(true));

		if (MapUtils.isNotEmpty(paginationRoleUser.getAttrs())) {
			model.putAll(paginationRoleUser.getAttrs());
		}

		return ContextHolder.getBean(JdbcTemplateSupport.class).pagination(mappedClass, new PaginationArgs(SqlIds.readByLikeCode.id(), SqlIds.findByLikeCode.id(), paginationRoleUser), model);
	}

	@Override
	public Integer readByCodeNqIdForCount(final RoleUserDto readRoleUser) {
		final String[] whereAndEqProperties = { Attributes.code.name() };

		final Model model = ModelUtils.newModel(new ModelArgs(readRoleUser, whereAndEqProperties));

		if (MapUtils.isNotEmpty(readRoleUser.getAttrs())) {
			model.putAll(readRoleUser.getAttrs());
		}

		final String[] whereAndNqProperties = EntityUtils.getWhereProperties(readRoleUser);

		if (ArrayUtils.isNotEmpty(whereAndNqProperties)) {
			ModelUtils.put(model, new ModelArgs(Model.Keys.whereAndNq.stringValue(), readRoleUser, whereAndNqProperties));
		}

		model.putTrue(Model.Keys.whereAndBetween.stringValue(), Attributes.sysdate.name());

		return ContextHolder.getBean(JdbcTemplateSupport.class).read(Integer.class, SqlIds.readByCode.id(), model);
	}

	@Override
	public <P> P saveByIdOrCode(final Class<P> mappedClass, final RoleUserDto saveRoleUser) {
		final P oldRoleUser = this.findByCodeOrId(mappedClass, saveRoleUser);

		if (oldRoleUser == null) {
			this.insertByCode(saveRoleUser);

			return this.findByCodeOrId(mappedClass, saveRoleUser);
		}

		final int updateCount = this.updateByCode(saveRoleUser, oldRoleUser);

		if (updateCount < 1) {
			return oldRoleUser;
		}

		return this.findByCodeOrId(mappedClass, saveRoleUser);
	}

	@Override
	public Map<String, Object> saveUserIdAndRoleIds(final String userId, final String roleIds) {
		final Map<String, Object> model = Maps.newHashMap();

		model.put(Attributes.userId.name(), userId);
		model.put("roleIds", roleIds);

		final Map<String, Object> returnMap = Maps.newHashMap();

		final int deleteCount = ContextHolder.getBean(JdbcTemplateSupport.class).update(SqlIds.deleteByUserIdAndNotRoleIds.id(), model);

		returnMap.put("deleteCount", deleteCount);

		if (StringUtils.isBlank(roleIds)) {
			return returnMap;
		}

		final List<Map<String, Object>> mapList = Lists.newArrayList();

		final List<String> roleIdList = Lists.newArrayList(StringUtils.split(roleIds, ","));

		for (final String roleId : roleIdList) {
			final Map<String, Object> map = Maps.newHashMap();

			map.put(Attributes.userId.name(), userId);
			map.put(Attributes.roleId.name(), roleId);

			mapList.add(map);
		}

		final int insertCount = ContextHolder.getBean(JdbcTemplateSupport.class).update(SqlIds.insertByUserIdAndRoleId.id(), mapList);

		returnMap.put("insertCount", insertCount);

		return returnMap;
	}

	@Override
	public int updateByCode(final RoleUserDto updateRoleUser) {
		final RoleUserDto oldRoleUser = this.findByCodeOrId(RoleUserDto.class, updateRoleUser);

		return this.updateByCode(updateRoleUser, oldRoleUser);
	}

	private <P> int updateByCode(final RoleUserDto updateRoleUser, final P oldRoleUser) {
		if (oldRoleUser == null) {
			return 0;
		}

		final String[] useProperties = EntityUtils.addNotNullTimeSegmentProperties(new String[] { Attributes.parentId.name(), Attributes.typeId.name(), Attributes.code.name(), Attributes.name.name(), Attributes.value.name(), Attributes.remark.name() }, updateRoleUser);

		final String[] updateProperties = com.cardone.common.util.BeanUtils.diffProperties(updateRoleUser, oldRoleUser, useProperties);

		if (ArrayUtils.isEmpty(updateProperties)) {
			return 0;
		}

		final String[] whereAndEqProperties = EntityUtils.getWhereProperties(oldRoleUser, Attributes.id.name());

		com.cardone.common.util.BeanUtils.copyProperties(oldRoleUser, updateRoleUser, whereAndEqProperties);

		final Model model = ModelUtils.newModel(new ModelArgs(Model.Keys.update.stringValue(), updateRoleUser, updateProperties), new ModelArgs(updateRoleUser, whereAndEqProperties));

		if (MapUtils.isNotEmpty(updateRoleUser.getAttrs())) {
			model.putAll(updateRoleUser.getAttrs());
		}

		return ContextHolder.getBean(JdbcTemplateSupport.class).update(SqlIds.updateByCode.id(), model);
	}
}